var DragEvent = {

    top: true,

    activeElement: undefined,
    previousElement: undefined,
    moveElementStyle: undefined,
    moveObject: {},
    addElement: undefined,

    setHandler: function (ev) {
        ev.stopPropagation();

        var target = ev.target.parentNode;
        var dataId = target.dataset.id;
        var element = ElementArray.getElementByDataId(dataId);
        var contentEditable = element.element.contentEditable;
        if (contentEditable !== 'true') {
            element.element.contentEditable  = true;
        }
        else {
            element.element.contentEditable  = false;
        }
        
    },

    clickHandler: function(ev) {
        if (document.querySelector('.input')) {
            removeSelectEvent();
        }

        var target = ev.target;
        var dataId = ev.target.dataset.id;
        var element = ElementArray.getElementByDataId(dataId);
        DragEvent.addElement = element;

        document.querySelector('.propertyList').innerHTML = element.createLayout();

        var styleObject = element.style;

        for (var key in styleObject) {
            document.getElementById(key).value = styleObject[key];
        }
        addSelectEvent();
    },

    // 开始拖拽的事件行为
    dragStartHandler: function (ev) {
        if (!ev.target.dataset.type) {
            return;
        }
        ev.effectAllowed = "copy";
        ev.dataTransfer.setData("text/plain", ev.target.dataset.name);
        ev.dataTransfer.setData("text/html", ev.target.dataset.type);
        DragEvent.activeElement = preLocation;

        if (ev.target.dataset.type == '2') {
            DragEvent.moveElementStyle = ev.target.style.cssText;
            DragEvent.moveObject.text = ev.target.textContent;
        }
        return true;
    },

    // 当拖拽到目标元素触发的行为
    dragEnterHandler: function (ev) {
        DragEvent.previousElement = DragEvent.activeElement;

        ev.stopPropagation();
        ev.preventDefault();

        if (ev.target.classList && ev.target.classList.contains('createElement')) {
            DragEvent.activeElement = ev.target;
        }
        
        return false;
    },

    //  拖拽在目标元素上面触发的行为,表示允许放置上面
    canDragOverHandler: function (ev) {
        ev.stopPropagation();
        ev.preventDefault();
        ev.dataTransfer.dropEffect = 'copy';
        var activeRect = DragEvent.activeElement.getBoundingClientRect();
        var mouseUp = ev.clientY - activeRect.top;
        if (DragEvent.activeElement.classList.contains("createElement")) {
            if (mouseUp > (activeRect.height / 2)) {
                DragEvent.activeElement.className = "createElement bottomAble";
                DragEvent.top = false;
            }
            else {
                DragEvent.activeElement.className = "createElement topAble";
                DragEvent.top = true;
            }
        }
        
        return false;
    },

    // 拖拽在目标元素上面触发的行为,表示不允许放置上面
    cantDragOverHandler: function (ev) {
        ev.stopPropagation();
        ev.preventDefault();
        ev.dataTransfer.dropEffect = 'none';
        return false;
    },

    //  在拖拽元素上离开发生的行为
    dragLeaveHandler: function (ev) {
        if (DragEvent.previousElement && DragEvent.previousElement.classList.contains("createElement")) {
            DragEvent.previousElement.className = "createElement";
        }
        return false;
    },

    //  拖拽行为结束后触发的行为
    dragEndHandler: function(ev) {
        if (DragEvent.previousElement && DragEvent.previousElement.classList.contains("createElement")) {
            DragEvent.previousElement.className = "createElement";
        }
        if (DragEvent.activeElement.classList.contains("createElement")) {
            DragEvent.activeElement.className = "createElement";
        }

        if (ev.target.dataset.type == '2') {
            var addElement = DragEvent.addElement;
            var targetElement = ev.target;
            var dataId = targetElement.dataset.id;
            var moveElement = ElementArray.getElementByDataId(dataId);

            var styleObject = moveElement.style;
            addElement.style = {};

            for (var key in styleObject) {
                addElement.style[key] = styleObject[key];
                addElement.element.style[key] = styleObject[key];
                document.getElementById(key).value = styleObject[key];
            }
            DragEvent.removeElement(ev);
        }
            
        return false;
    },

    removeElement: function (ev) {
        ev.stopPropagation();
        var target = ev.target;
        if (!ev.target.classList.contains("createElement")) {
            target = target.parentNode;
        }
        var dataId = target.dataset.id;
        var element = ElementArray.getElementByDataId(dataId);
        element.remove();

        if (document.querySelector(".input")) {
            removeSelectEvent();
        }
        document.querySelector('.propertyList').innerHTML = '';
    },

    //  不能放置元素的放置后的行为
    cantDropHandler: function (ev) {
        ev.dataTransfer.dropEffect = 'none';
        ev.preventDefault();
        ev.stopPropagation();
    },

    //  放置元素的后的行为
    dropHandler: function(ev) {
        ev.dataTransfer.dropEffect = "copy";
        ev.preventDefault();
        ev.stopPropagation();

        var target = ev.target;
        var text = ev.dataTransfer.getData("text/plain");
        var type = ev.dataTransfer.getData("text/html");
        var element = DragEvent.createElement(text, text);
        DragEvent.addElement = element;
        var activeElement = DragEvent.activeElement;
        
        var thisElement = element.create();
        if (type == '2') {
            thisElement = element.create(DragEvent.moveObject.text);
        }

        if (target.nodeName.toLowerCase() == "svg" || target.id === "editArea") {
            editArea.insertBefore(thisElement, preLocation);
            ElementArray.push(element);
        }
        else if (DragEvent.parentIsCreateElement(target) && DragEvent.top) {
            editArea.insertBefore(thisElement, activeElement);
            var dataId = activeElement.dataset.id;
            var i = ElementArray.getIndexByDataId(dataId);
            ElementArray.add(i, element);
        } 
        else {
            if (activeElement !== preLocation.previousElementSibling) {
                editArea.insertBefore(thisElement, activeElement.nextElementSibling);

                var dataId = activeElement.dataset.id;
                var i = ElementArray.getIndexByDataId(dataId);
                ElementArray.add(i + 1, element);
            }
            else {
                editArea.insertBefore(thisElement, preLocation);
                ElementArray.push(element);
            }
        }

        if (type == '2') {
            thisElement.style.cssText = DragEvent.moveElementStyle;
        }

        if (document.querySelector(".input")) {
            removeSelectEvent();
        }
        document.querySelector('.propertyList').innerHTML = element.createLayout();
        addSelectEvent();
    },

    createElement: function (text, textStr) {
        var combineElement = new CombineElement(text);
        return combineElement;
    },

    parentIsCreateElement: function (element) {
        if (element.classList.contains("createElement")) {
            return true;
        }

        var parentElement = element.parentElement;
        while (parentElement !== editArea) {
            if (parentElement.classList.contains("createElement")) {
                return true;
            }
            parentElement = parentElement.parentElement;
        }

        return false;
    },

    
};

function CombineElement(str) {
    this.str = str;
    this.dataId = +new Date();
    this.element = document.createElement("div");
    this.style = {};
}

CombineElement.prototype.create = function (textStr) {
    var str = this.str;
    var element = this.element;

    switch (str) {
        case 'div':
            element.textContent = textStr ? textStr : "文本组件";
            element.className = 'createElement';
            break;
        default: 
            var tempElement = document.createElement(str);
            tempElement.textContent = textStr ? textStr : '其它组件';
            element.className = 'createElement';
            element.appendChild(tempElement);
    }

    var setElement = document.createElement('div');
    setElement.className = "set";

    var minusElement = document.createElement('div');
    minusElement.className = "minus";

    element.draggable = true;
    element.dataset.type = '2';
    element.dataset.name = str;
    element.appendChild(minusElement);
    element.appendChild(setElement);
    element.dataset.id = this.dataId;

    setElement.addEventListener('click', DragEvent.setHandler, false);
    minusElement.addEventListener("click", DragEvent.removeElement, false);
    element.addEventListener("dragstart", DragEvent.dragStartHandler, false);
    element.addEventListener("dragend", DragEvent.dragEndHandler, false);
    element.addEventListener("click", DragEvent.clickHandler, false);

    return element;
};

CombineElement.prototype.remove = function () {
    var element = this.element;
    element.querySelector('.minus').removeEventListener('click', DragEvent.removeElement, false);
    element.querySelector('.set').removeEventListener('click', DragEvent.setHandler, false);
    element.removeEventListener("dragstart", DragEvent.dragStartHandler, false);
    element.removeEventListener("dragend", DragEvent.dragEndHandler, false);
    element.removeEventListener('click', DragEvent.clickHandler, false);
    var dataId = element.dataset.id;
    var index = ElementArray.getIndexByDataId(dataId);
    ElementArray.remove(index);
    element.outerHTML = '';
};

CombineElement.prototype.createLayout = function () {
    var str = this.str;
    var config = strKeyArray[str];
    var tempHtml = '<div class="title">基本布局</div>';
    var temlUl = document.createElement('ul');

    for (var key in config) {
        var configObj = config[key];
        var idKey = configObj.key
        var dataKey = configObj.data;
        var forData = configObj.forData;
        var li = document.createElement('li');
        var label = document.createElement("label");
        label.htmlFor = idKey;
        label.className = 'label';
        label.textContent = key;
        var selectElement = document.createElement("select");
        selectElement.id = idKey;
        selectElement.className = 'input';

        for (var i = 0, len = dataKey.length; i < len; i++) {
            var option = document.createElement('option');
            option.value = forData[i];
            option.textContent = dataKey[i];
            selectElement.appendChild(option);
        }

        li.appendChild(label);
        li.appendChild(selectElement);
        temlUl.appendChild(li);
    }

    return tempHtml + temlUl.outerHTML;
}

var ElementArray = {
    length: 0,

    push: function (element) {
        Array.prototype.push.call(this, element);
    },

    remove: function (i) {
        Array.prototype.splice.call(this, i, 1);
    },

    add: function (i, element) {
        Array.prototype.splice.call(this, i, 0, element);
    },

    getElementByDataId: function(dataId) {
        var length = this.length;

        for (var i = 0; i < length; i++) {
            if (this[i].dataId == dataId) {
                break;
            }
        }

        return this[i];
    },

    getIndexByDataId: function (dataId) {
        var length = this.length;

        for (var i = 0; i < length; i++) {
            if (this[i].dataId == dataId) {
                break;
            }
        }

        return i;
    }
}

function addSelectEvent() {
    var selectArray = document.querySelectorAll("select.input");
    [].forEach.call(selectArray, function (select) {
        select.addEventListener('change', change, false);
    });
}

function removeSelectEvent() {
    var selectArray = document.querySelectorAll("select.input");
    [].forEach.call(selectArray, function (select) {
        select.removeEventListener('change', change, false);
    });
}

function change(ev) {
    var target = ev.target;
    var id = target.id;
    DragEvent.addElement.element.style[id] = target.value;
    DragEvent.addElement.style[id] = target.value;
}